import $ from 'jquery'

class Unit {
  constructor(ele) {
    // 通过父类保存参数
    this.curEle = ele
  }
}

// 渲染 文本 组件
class ReactTextUnit extends Unit {
  getMarkUp(rootId) {
    this._rootId = rootId
    return `<span data-reactid=${rootId}>${this.curEle}</span>`;
  }
}

// 渲染 jsx 组件
class ReactNativeUnit extends Unit {
  getMarkUp(rootId) {
    this._rootId = rootId
    let { type, props } = this.curEle;
    let tagStart = `<${type} data-reactid="${rootId}"`
    let tagEnd = `</${type}>`
    let contentStr = ''
    for (const propName in props) {
      if (propName.startsWith('on')) {
        let eventType = propName.slice(2).toLowerCase()
        // 事件委托
        $(document).on(eventType, `[data-reactid="${rootId}"]`, props[propName])
      } else if (propName === 'children') {
        contentStr = props[propName].map((child, idx) => {
          let childInstance = createReactUnit(child)
          return childInstance.getMarkUp(`${rootId}.${idx}`)
        }).join('')
      } else {
        tagStart += ` ${propName}="${props[propName]}"`
      }
    }
    return tagStart + '>' + contentStr + tagEnd
  }
}

// 渲染 类组件
class ReactCompositUnit extends Unit {
  getMarkUp(rootId) {
    this._rootId = rootId
    let { type: Component, props } = this.curEle
    let componentInstance = new Component(props)

    // 创建实例后，即将挂载
    componentInstance.componentWillMount && componentInstance.componentWillMount()


    // 调用 render 后返回的结果
    let reactComponentRenderer = componentInstance.render()
    // 递归渲染 返回的结果 (先序深度优先， 递归树)
    let reactCompositUnit = createReactUnit(reactComponentRenderer)
    // console.log("reactCompositUnit", reactCompositUnit);
    let markUp = reactCompositUnit.getMarkUp(rootId)
    // console.log("markUp", markUp);
    // 深层组件先挂载完成，(在递归之后执行，由内而外)
    $(document).on('mounted', () => {
      componentInstance.componentDidMount && componentInstance.componentDidMount()
    })
    return markUp
  }
}

function createReactUnit(ele) {
  if (typeof ele === 'string' || typeof ele === 'number') {
    return new ReactTextUnit(ele)
  }
  if (typeof ele === 'object' && typeof ele.type === 'string') {
    return new ReactNativeUnit(ele)
  }
  if (typeof ele === 'object' && typeof ele.type == 'function') {
    return new ReactCompositUnit(ele)
  }
}

export default createReactUnit